﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// This target can receive damage.
/// </summary>
public class DamageTaker : MonoBehaviour
{
    // 初始生命值（最大值）
    public int hitpoints = 1;
    // 当前剩余生命值，在运行时动态变化
    [HideInInspector]
    public int currentHitpoints;
    // 受伤视觉效果的持续时间
    public float damageDisplayTime = 0.2f;
    // 血条对象的引用，用于动态调整其宽度
    public Transform healthBar;
    // 是否在受伤时发送消息（触发事件）
    public bool isTrigger;

    // 控制该对象的可视图像组件，用于颜色变化反馈
    private SpriteRenderer sprite;
    // 是否正在进行视觉效果协程，避免重复触发
    private bool coroutineInProgress;
    // 血条的初始宽度，用于计算当前血量对应的比例
    private float originHealthBarWidth;

    public delegate bool DeathHandler();
    public event DeathHandler OnDeath;

    /// <summary>
    /// 获取 SpriteRenderer，初始化 currentHitpoints，并进行参数校验。
    /// </summary>
    void Awake()
    {
        currentHitpoints = hitpoints;
        sprite = GetComponentInChildren<SpriteRenderer>();
        Debug.Assert(sprite && healthBar, "Wrong initial parameters");
    }

    /// <summary>
    /// 记录血条原始宽度。
    /// </summary>
    void Start()
    {
        originHealthBarWidth = healthBar.localScale.x;
    }

    /// <summary>
    /// 判断是伤害还是治疗，更新生命值和血条；如果生命值归零则执行死亡。
    /// </summary>
    /// <param name="damage">Damage.</param>
    public void TakeDamage(int damage)
    {
        if (damage > 0 && this.enabled)
        {
            // 如果挂载了 LowHealthShield 组件，且护盾已激活，则减半伤害
            var shield = GetComponent<LowHealthShield>();
            if (shield != null && shield.IsShieldActive)
            {
                damage = Mathf.CeilToInt(damage * 0.5f);
            }

            if (currentHitpoints > damage)
            {
                currentHitpoints -= damage;
                UpdateHealthBar();
                if (!coroutineInProgress) StartCoroutine(DisplayDamage());
                if (isTrigger) SendMessage("OnDamage");
            }
            else
            {
                currentHitpoints = 0;
                UpdateHealthBar();
                Die();
            }
        }
        else if (damage < 0) // 治疗
        {
            currentHitpoints = Mathf.Min(currentHitpoints - damage, hitpoints);
            UpdateHealthBar();
        }
    }

    /// <summary>
    /// 根据当前生命值缩放血条宽度。
    /// </summary>
    public void UpdateHealthBar()
    {
        float healthBarWidth = originHealthBarWidth * currentHitpoints / hitpoints;
        healthBar.localScale = new Vector2(healthBarWidth, healthBar.localScale.y);
    }

    /// <summary>
    /// 触发事件 UnitKilled 并销毁该游戏对象。逻辑死亡阶段，仍可操作对象
    /// </summary>
    public void Die()
    {
        bool cancelled = false;
        if (OnDeath != null)
        {
            foreach (DeathHandler handler in OnDeath.GetInvocationList())
                if (handler.Invoke())
                {
                    cancelled = true;
                    break;
                }
        }

        if (cancelled)
            return;

        EventManager.TriggerEvent("UnitKilled", gameObject, null);
        Destroy(gameObject);
    }

    /// <summary>
    /// 执行视觉反馈，将精灵颜色在黑色和原始色之间闪烁。
    /// </summary>
    /// <returns>The damage.</returns>
    IEnumerator DisplayDamage()
    {
        coroutineInProgress = true;
        Color originColor = sprite.color;
        float counter;
        // Set color to black and return to origin color over time
		for (counter = 0f; counter < damageDisplayTime; counter += Time.fixedDeltaTime)
        {
            sprite.color = Color.Lerp(originColor, Color.black, Mathf.PingPong(counter, damageDisplayTime));
			yield return new WaitForFixedUpdate();
        }
        sprite.color = originColor;
        coroutineInProgress = false;
    }

    /// <summary>
    /// 触发 UnitDie 事件，停止所有协程。对象销毁阶段，不可再使用对象
    /// </summary>
    void OnDestroy()
	{
		EventManager.TriggerEvent("UnitDie", gameObject, null);
		StopAllCoroutines();
	}
}
